import { Layout } from "@/components/layout/layout";
import withAuth, { getServerSideProps } from "@/hoc/withAuth";
import { useHttp } from "@/hooks";
import useMounted from "@/hooks/useMounted";
import type { NextPage, GetServerSidePropsContext } from "next";
import { useRouter } from "next/router";
import { useEffect, useRef, useState } from "react";
import React from "react";
import {
  Table,
  TableHeader,
  TableColumn,
  TableBody,
  TableRow,
  TableCell,
  getKeyValue,
  Button,
  Image,
  Chip,
  Avatar,
  Link,
} from "@nextui-org/react";
import { User } from "@/entities/User";
import { capitalize } from "@/utils/base";
import dayjs from "dayjs";
import AppModal from "@/components/modal/appModal";
import { App } from "@/entities/App";
import SecretModal from "@/components/modal/secretModal";
import {
  Add,
  AddBoxOutlined,
  AddCircleOutline,
  AddSharp,
  BlockSharp,
  CheckCircleOutline,
} from "@mui/icons-material";
import UserModal from "@/components/modal/userModal";

const AppsPage: NextPage = () => {
  const [apps, setApps] = useState<App[]>([]);
  const [visible, setVisible] = useState(false);
  const [secretModalVisible, setSecretModalVisible] = useState(false);
  const [userModalVisible, setUserModalVisible] = useState(false);
  const { http } = useHttp();
  const [curAppId, setCurAppId] = useState<number>();
  const router = useRouter();

  const goDataset = (appid: number) => {
    router.push({
      pathname: "/datasets",
      query: { appid },
    });
  };

  const getAppList = async (silent = false) => {
    const res = await http.get(
      "/api/app/list",
      {},
      { isOpenLoading: true, silent }
    );
    if (res?.success) {
      setApps(res.data as App[]);
    }
  };

  const getAppListRef = useRef(getAppList);

  useMounted(() => {
    getAppListRef.current();
  });

  const cols = [
    "id",
    "name",
    "introduce",
    "type",
    // "createdAt",
    "admin",
    "users",
    "isDelete",
    "operation",
  ];
  const getWidth = (key: string) => {
    if (key === "operation") {
      return 300;
    } else if (key === "id") {
      return 100;
    } else if (key === "introduce") {
      return 300;
    } else if (key === "name" || key === "users") {
      return 200;
    } else {
      return 100;
    }
  };
  const columns = cols.map((col) => ({
    key: col,
    width: getWidth(col),
    label:
      col == "isDelete" ? "Status" : capitalize(col.replace(/[A-Z]/g, " $&")),
  }));

  const handleDelUser = async (appid: number, userid: number) => {
    const res = await http.post(
      "api/app/user/remove",
      { appid, userid },
      { isOpenLoading: true }
    );
    if (res?.success) {
      getAppListRef.current(true);
    }
  };

  const getVal = (item: App, key: string | number) => {
    // debugger;
    const val = getKeyValue(item, key);
    if (key === "admin") {
      const admin = val as User;
      return (
        <Chip
          size="sm"
          startContent={
            <Avatar
              className="w-4 h-4"
              name={admin.name}
              src={admin.avatarData}
            />
          }
          color={"success"}
          variant="flat"
        >
          {admin.name}
        </Chip>
      );
    } else if (key === "name") {
      return (
        <Link color="primary" href={`/configs?appid=${item.id}`}>
          {val}
        </Link>
      );
    } else if (key === "users") {
      const users = val as User[];
      return (
        <div className="flex flex-wrap items-center justify-center gap-2">
          {users.map((user) => (
            <Chip
              key={user.id}
              size="sm"
              onClose={
                // @ts-ignore
                item.admin.id !== user.id
                  ? () => handleDelUser(item.id, user.id)
                  : undefined
              }
              startContent={
                <Avatar
                  className="w-4 h-4"
                  name={user.name}
                  src={user.avatarData}
                />
              }
              color={"default"}
              variant="flat"
            >
              {user.name}
            </Chip>
          ))}
          <AddCircleOutline
            onClick={() => handleAddUser(item.id)}
            className="text-md text-gray-300 hover:text-gray-500 cursor-pointer"
          />
        </div>
      );
    } else if (key === "isDelete") {
      const statusVal = val ? "disabled" : "active";
      return (
        <Chip
          size="sm"
          startContent={
            statusVal === "disabled" ? (
              <BlockSharp className="text-md" />
            ) : (
              <CheckCircleOutline className="text-md" />
            )
          }
          color={statusVal === "disabled" ? "warning" : "success"}
          variant="flat"
        >
          {statusVal}
        </Chip>
      );
    } else if (key === "createdAt") {
      const day = dayjs(val).format("YYYY-MM-DD HH:mm:ss");
      return day;
    } else {
      return val;
    }
  };

  const handleChangeStatus = async (isDelete: number, id: number) => {
    const res = await http.post(
      "/api/app/status",
      { isDelete, id },
      { isOpenLoading: true }
    );
    if (res?.success) {
      getAppListRef.current(true);
    }
  };

  const onAppCreated = (success: boolean) => {
    success && getAppListRef.current(true);
  };

  const handleEditApp = (id: number) => {
    setCurAppId(id);
    setVisible(true);
  };

  const handleViewSecret = (id: number) => {
    setCurAppId(id);
    setSecretModalVisible(true);
  };

  const handleAddUser = (id: number) => {
    setCurAppId(id);
    setUserModalVisible(true);
  };

  return (
    <div className="apps-page px-6 py-3">
      <SecretModal
        mode="edit"
        confirmBtnText="Copy"
        appId={curAppId}
        visible={secretModalVisible}
        closeCallback={() => setSecretModalVisible(false)}
      />

      <UserModal
        mode="edit"
        confirmBtnText="Add"
        appId={curAppId}
        visible={userModalVisible}
        closeCallback={() => setUserModalVisible(false)}
        confirmCallback={() => getAppListRef.current(true)}
      />
      <AppModal
        mode="edit"
        visible={visible}
        closeCallback={() => setVisible(false)}
        appId={curAppId}
        confirmCallback={onAppCreated}
      />

      <div className="actions text-right mb-4">
        <AppModal mode="create" confirmCallback={onAppCreated} />
      </div>
      <Table className="text-center" aria-label="apps table">
        <TableHeader columns={columns}>
          {(column) => (
            <TableColumn
              className="text-center"
              align="end"
              width={column.width}
              allowsResizing
              key={column.key}
            >
              {column.label}
            </TableColumn>
          )}
        </TableHeader>
        <TableBody items={apps} emptyContent="no data">
          {(item) => (
            <TableRow key={item.id}>
              {(columnKey) =>
                columnKey === "operation" ? (
                  <TableCell>
                    <Button
                      variant="flat"
                      className="m-2 rounded-md"
                      size="sm"
                      color="primary"
                      onClick={() => handleEditApp(item.id)}
                    >
                      Edit
                    </Button>
                    <Button
                      variant="flat"
                      className="m-2 rounded-md"
                      size="sm"
                      color="primary"
                      onClick={() => handleViewSecret(item.id)}
                    >
                      Secret
                    </Button>
                    {!item.isDelete ? (
                      <Button
                        variant="flat"
                        className="m-2 rounded-md"
                        size="sm"
                        color="danger"
                        onClick={() => handleChangeStatus(1, item.id)}
                      >
                        Disable
                      </Button>
                    ) : (
                      <Button
                        variant="flat"
                        className="m-2 rounded-md"
                        size="sm"
                        color="danger"
                        onClick={() => handleChangeStatus(0, item.id)}
                      >
                        Enable
                      </Button>
                    )}

                    <Button
                      variant="flat"
                      className="m-2 rounded-md"
                      size="sm"
                      color="secondary"
                      onClick={() => goDataset(item.id)}
                    >
                      Dataset
                    </Button>
                  </TableCell>
                ) : (
                  <TableCell>
                    <div
                      className={
                        "cell-value " +
                        (["introduce"].includes(columnKey as string)
                          ? "line-clamp-2"
                          : "")
                      }
                    >
                      {getVal(item, columnKey)}
                    </div>
                  </TableCell>
                )
              }
            </TableRow>
          )}
        </TableBody>
      </Table>
    </div>
  );
};

export { getServerSideProps };

export default withAuth(AppsPage);
